﻿#region 命名空间

using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;

#endregion

namespace Sharp.Infrastructure
{
    /// <summary>
    ///     处理HTML
    /// </summary>
    public class HTML
    {
        #region 去除脚本

        /// <summary>
        ///     去除脚本
        /// </summary>
        /// <param name="htmlstring"></param>
        /// <returns></returns>
        public static string NoJs(string htmlstring)
        {
            if (string.IsNullOrEmpty(htmlstring))
            {
                return string.Empty;
            }
            htmlstring = RegexHepler.Javascript.Replace(htmlstring, "");

            return htmlstring;
        }

        #endregion

        /// <summary>
        ///     去除HTML标记
        /// </summary>
        /// <param name="htmlstring"></param>
        /// <param name="tag"></param>
        /// <returns></returns>
        public static string NoHtml(string htmlstring, WebSourceTag tag)
        {
            if (tag.HasFlag(WebSourceTag.All))
            {
                return NoHtml(htmlstring);
            }
            if (string.IsNullOrEmpty(htmlstring))
            {
                return string.Empty;
            }
            if (tag.HasFlag(WebSourceTag.Note))
            {
                htmlstring = RegexHepler.HtmlNote.Replace(htmlstring, "").Trim();
            }
            if (tag.HasFlag(WebSourceTag.Script))
            {
                htmlstring = NoJs(htmlstring);
            }
            if (tag.HasFlag(WebSourceTag.Invisible))
            {
                htmlstring = RegexHepler.Invisible.Replace(htmlstring, " ").Trim();
            }
            if (tag.HasFlag(WebSourceTag.Style))
            {
                htmlstring = RegexHepler.Style.Replace(htmlstring, "").Trim();
            }
            return htmlstring.Trim();
        }

        #region 去除HTML标记

        /// <summary>
        ///     去除HTML标记
        /// </summary>
        /// <param name="Htmlstring">包括HTML的源码 </param>
        /// <returns>已经去除后的文字</returns>
        public static string NoHtml(string Htmlstring)
        {
            if (string.IsNullOrEmpty(Htmlstring) == true)
            {
                return string.Empty;
            }

            Htmlstring = Regex.Replace(Htmlstring, "<[^>]*>", "");
            Htmlstring = Regex.Replace(Htmlstring, @"([\r\n])[\s]+", " ");
            //Htmlstring = Htmlstring.Replace(@"-->", "");
            return Htmlstring.Replace("&nbsp;", " ");
        }

        /// <summary>
        ///     去除HTML标记
        /// </summary>
        /// <param name="htmlstring">包括HTML的源码 </param>
        /// <returns>已经去除后的文字</returns>
        public static string RemoveHtmlTags(string htmlstring)
        {
            char[] array = new char[htmlstring.Length];
            int arrayIndex = 0;
            bool inside = false;

            for (int i = 0; i < htmlstring.Length; i++)
            {
                char let = htmlstring[i];
                if (let == '<')
                {
                    inside = true;
                    continue;
                }
                if (let == '>')
                {
                    inside = false;
                    continue;
                }
                if (!inside)
                {
                    array[arrayIndex] = let;
                    arrayIndex++;
                }
            }
            return new string(array, 0, arrayIndex);
        }

        #endregion

        #region 清理Word生成的冗余HTML

        /// <summary>
        ///     清理Word生成的冗余HTML
        /// </summary>
        /// <param name="html"></param>
        /// <returns></returns>
        public static string CleanWordHtml(string html)
        {
            StringCollection sc = new StringCollection
            {
                @"<!--(\w|\W)+?-->",
                @"<title>(\w|\W)+?</title>",
                @"\s?class=\w+",
                @"\s+style='[^']+'",
                @"<(meta|link|/?o:|/?style|/?font|/?strong|/?st\d|/?head|/?html|body|/?body|/?span|!\[)[^>]*?>",
                @"(<[^>]+>)+ (</\w+>)+",
                @"\s+v:\w+=""[^""]+""",
                @"(\n\r){2,}"
            };
            // get rid of unnecessary tag spans (comments and title)
            // Get rid of classes and styles
            // Get rid of unnecessary tags
            //sc.Add(@"<(meta|link|/?o:|/?style|/?div|/?st\d|/?head|/?html|body|/?body|/?span|!\[)[^>]*?>");
            // Get rid of empty paragraph tags
            // remove bizarre v: element attached to <img> tag
            // remove extra lines

            return sc.Cast<string>()
                .Aggregate(html, (current, s) => Regex.Replace(current, s, "", RegexOptions.IgnoreCase));
        }

        #endregion

        #region Text2Html

        /// <summary>
        ///     将C＃中的回车(\r)和空格(" ")换成HTML格式对应的换行和空格
        /// </summary>
        /// <param name="strInPut"></param>
        /// <returns></returns>
        public static string Text2Html(string strInPut)
        {
            StringBuilder temp = new StringBuilder();
            temp.Append(strInPut);

            temp.Replace(" ", "&nbsp;");
            temp.Replace("<", "&lt;");
            temp.Replace(">", "&gt;");
            temp.Replace("\r", "<br>");
            //Temp.Replace("&","&amp;");
            temp.Replace("\"", "&quot;");
            return temp.ToString();
        }

        #endregion

        #region Html2Text

        /// <summary>
        ///     将HTML格式的换行和空格换成C＃中的对应字符("\r"、" ")
        /// </summary>
        /// <param name="strInPut"></param>
        /// <returns></returns>
        public static string Html2Text(string strInPut)
        {
            StringBuilder temp = new StringBuilder();
            temp.Append(strInPut);

            temp.Replace("<br>", "\r");
            temp.Replace("&nbsp;", " ");
            temp.Replace("&lt;", "<");
            temp.Replace("&gt;", ">");
            //Temp.Replace("&amp;","&");
            temp.Replace("&quot;", "\"");
            return temp.ToString();
        }

        #endregion

        #region UBB代码

        /// <summary>
        ///     UBB代码
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static string Ubb2Html(string str)
        {
            StringBuilder outPut = new StringBuilder(str);
            Match match1 = new Regex(@"(\[b\])([ \S\t]*?)(\[\/b\])", RegexOptions.IgnoreCase).Match(outPut.ToString());
            while (match1.Success)
            {
                outPut.Replace(match1.Groups[0].Value, "<B>" + match1.Groups[2].Value + "</B>");
                match1 = match1.NextMatch();
            }
            match1 = new Regex(@"(\[i\])([ \S\t]*?)(\[\/i\])", RegexOptions.IgnoreCase).Match(outPut.ToString());
            while (match1.Success)
            {
                outPut.Replace(match1.Groups[0].Value, "<I>" + match1.Groups[2].Value + "</I>");
                match1 = match1.NextMatch();
            }
            match1 = new Regex(@"(\[U\])([ \S\t]*?)(\[\/U\])", RegexOptions.IgnoreCase).Match(outPut.ToString());
            while (match1.Success)
            {
                outPut.Replace(match1.Groups[0].Value, "<U>" + match1.Groups[2].Value + "</U>");
                match1 = match1.NextMatch();
            }
            match1 =
                new Regex(@"((\r\n)*\[p\])(.*?)((\r\n)*\[\/p\])", RegexOptions.Singleline | RegexOptions.IgnoreCase)
                    .Match(outPut.ToString());
            while (match1.Success)
            {
                outPut.Replace(match1.Groups[0].Value, "<P class=\"pstyle\">" + match1.Groups[3].ToString() + "</P>");
                match1 = match1.NextMatch();
            }
            match1 = new Regex(@"(\[sup\])([ \S\t]*?)(\[\/sup\])", RegexOptions.IgnoreCase).Match(outPut.ToString());
            while (match1.Success)
            {
                outPut.Replace(match1.Groups[0].Value, "<SUP>" + match1.Groups[2].Value + "</SUP>");
                match1 = match1.NextMatch();
            }
            match1 = new Regex(@"(\[sub\])([ \S\t]*?)(\[\/sub\])", RegexOptions.IgnoreCase).Match(outPut.ToString());
            while (match1.Success)
            {
                outPut.Replace(match1.Groups[0].Value, "<SUB>" + match1.Groups[2].Value + "</SUB>");
                match1 = match1.NextMatch();
            }
            match1 = new Regex(@"(\[url\])([ \S\t]*?)(\[\/url\])", RegexOptions.IgnoreCase).Match(outPut.ToString());
            while (match1.Success)
            {
                outPut.Replace(match1.Groups[0].Value,
                    "<A href=\"" + match1.Groups[2].Value + "\" target=\"_blank\">" + match1.Groups[2].Value + "</A>");
                match1 = match1.NextMatch();
            }
            match1 =
                new Regex(@"(\[url=([ \S\t]+)\])([ \S\t]*?)(\[\/url\])", RegexOptions.IgnoreCase).Match(
                    outPut.ToString());
            while (match1.Success)
            {
                outPut.Replace(match1.Groups[0].Value,
                    "<A href=\"" + match1.Groups[2].Value + "\" target=\"_blank\">" + match1.Groups[3].ToString() +
                    "</A>");
                match1 = match1.NextMatch();
            }
            match1 = new Regex(@"(\[email\])([ \S\t]*?)(\[\/email\])", RegexOptions.IgnoreCase).Match(outPut.ToString());
            while (match1.Success)
            {
                outPut.Replace(match1.Groups[0].Value,
                    "<A href=\"mailto:" + match1.Groups[2].Value + "\" target=\"_blank\">" + match1.Groups[2].Value +
                    "</A>");
                match1 = match1.NextMatch();
            }
            match1 =
                new Regex(@"(\[email=([ \S\t]+)\])([ \S\t]*?)(\[\/email\])", RegexOptions.IgnoreCase).Match(
                    outPut.ToString());
            while (match1.Success)
            {
                outPut.Replace(match1.Groups[0].Value,
                    "<A href=\"mailto:" + match1.Groups[2].Value + "\" target=\"_blank\">" + match1.Groups[3].ToString() +
                    "</A>");
                match1 = match1.NextMatch();
            }
            match1 =
                new Regex(@"(\[size=([1-7])\])([ \S\t]*?)(\[\/size\])", RegexOptions.IgnoreCase).Match(outPut.ToString());
            while (match1.Success)
            {
                outPut.Replace(match1.Groups[0].Value,
                    "<FONT SIZE=" + match1.Groups[2].Value + ">" + match1.Groups[3].ToString() + "</FONT>");
                match1 = match1.NextMatch();
            }
            match1 =
                new Regex(@"(\[color=([\S]+)\])([ \S\t]*?)(\[\/color\])", RegexOptions.IgnoreCase).Match(
                    outPut.ToString());
            while (match1.Success)
            {
                outPut.Replace(match1.Groups[0].Value,
                    "<FONT COLOR=" + match1.Groups[2].Value + ">" + match1.Groups[3].ToString() + "</FONT>");
                match1 = match1.NextMatch();
            }
            match1 =
                new Regex(@"(\[font=([\S]+)\])([ \S\t]*?)(\[\/font\])", RegexOptions.IgnoreCase).Match(outPut.ToString());
            while (match1.Success)
            {
                outPut.Replace(match1.Groups[0].Value,
                    "<FONT FACE=" + match1.Groups[2].Value + ">" + match1.Groups[3].ToString() + "</FONT>");
                match1 = match1.NextMatch();
            }
            match1 = new Regex(@"\[picture\](\d+?)\[\/picture\]", RegexOptions.IgnoreCase).Match(outPut.ToString());
            while (match1.Success)
            {
                outPut.Replace(match1.Groups[0].Value,
                    "<A href=\"ShowImage.aspx?Type=ALL&Action=forumImage&ImageID=" + match1.Groups[1].ToString() +
                    "\" target=\"_blank\"><IMG border=0 Title=\u70b9\u51fb\u6253\u5f00\u65b0\u7a97\u53e3\u67e5\u770b src=\"ShowImage.aspx?Action=forumImage&ImageID=" +
                    match1.Groups[1].ToString() + "\"></A>");
                match1 = match1.NextMatch();
            }
            match1 =
                new Regex(@"(\[align=([\S]+)\])([ \S\t]*?)(\[\/align\])", RegexOptions.IgnoreCase).Match(
                    outPut.ToString());
            while (match1.Success)
            {
                outPut.Replace(match1.Groups[0].Value,
                    "<P align=" + match1.Groups[2].Value + ">" + match1.Groups[3].ToString() + "</P>");
                match1 = match1.NextMatch();
            }
            match1 = new Regex(@"(\[H=([1-6])\])([ \S\t]*?)(\[\/H\])", RegexOptions.IgnoreCase).Match(outPut.ToString());
            while (match1.Success)
            {
                outPut.Replace(match1.Groups[0].Value,
                    "<H" + match1.Groups[2].Value + ">" + match1.Groups[3].ToString() + "</H" + match1.Groups[2].Value +
                    ">");
                match1 = match1.NextMatch();
            }
            match1 =
                new Regex(@"(\[list(=(A|a|I|i| ))?\]([ \S\t]*)\r\n)((\[\*\]([ \S\t]*\r\n))*?)(\[\/list\])",
                    RegexOptions.IgnoreCase).Match(outPut.ToString());
            while (match1.Success)
            {
                string text2 = match1.Groups[5].ToString();
                Regex regex2 = new Regex(@"\[\*\]([ \S\t]*\r\n?)", RegexOptions.IgnoreCase);
                for (Match match2 = regex2.Match(text2); match2.Success; match2 = match2.NextMatch())
                {
                    text2 = text2.Replace(match2.Groups[0].ToString(), "<LI>" + match2.Groups[1]);
                }
                outPut.Replace(match1.Groups[0].Value,
                    "<UL TYPE=\"" + match1.Groups[3].ToString() + "\"><B>" + match1.Groups[4].ToString() + "</B>" +
                    text2 + "</UL>");
                match1 = match1.NextMatch();
            }
            match1 =
                new Regex(@"\[shadow=(?<x>[^\]]*),(?<y>[^\]]*),(?<z>[^\]]*)\](?<w>[^\]]*)\[/shadow\]",
                    RegexOptions.IgnoreCase).Match(outPut.ToString());
            while (match1.Success)
            {
                outPut.Replace(match1.Groups[0].Value,
                    @"<table width=" + match1.Groups[1] + " style=\"filter:shadow(color=" + match1.Groups[2] +
                    ", strength=" + match1.Groups[3] + ")\">" + match1.Groups[4] + "</table>");

                match1 = match1.NextMatch();
            }
            match1 =
                new Regex(@"(\[glow=)(\d*?),(#*\w*?),(\d*?)\]([\S\t]*?)(\[\/glow\])", RegexOptions.IgnoreCase).Match(
                    outPut.ToString());
            while (match1.Success)
            {
                outPut.Replace(match1.Groups[0].Value,
                    "<TABLE WIDTH=" + match1.Groups[2].Value + "  STYLE=FILTER:GLOW(COLOR=" +
                    match1.Groups[3].ToString() + ", STRENGTH=" + match1.Groups[4].ToString() + ")>" +
                    match1.Groups[5].ToString() + "</TABLE>");
                match1 = match1.NextMatch();
            }
            match1 =
                new Regex(@"(\[center\])([ \S\t]*?)(\[\/center\])", RegexOptions.IgnoreCase).Match(outPut.ToString());
            while (match1.Success)
            {
                outPut.Replace(match1.Groups[0].Value, "<CENTER>" + match1.Groups[2].Value + "</CENTER>");
                match1 = match1.NextMatch();
            }
            match1 =
                new Regex(@"(\[IMG\])(http|https|ftp):\/\/([ \S\t]*?)(\[\/IMG\])", RegexOptions.IgnoreCase).Match(
                    outPut.ToString());
            while (match1.Success)
            {
                outPut.Replace(match1.Groups[0].Value,
                    "<br><a onfocus=this.blur() href=" + match1.Groups[2].Value + "://" + match1.Groups[3].ToString() +
                    " target=_blank><IMG SRC=" + match1.Groups[2].Value + "://" + match1.Groups[3].ToString() +
                    " border=0 onload=javascript:if(screen.width-333<this.width)this.width=screen.width-333></a>");
                match1 = match1.NextMatch();
            }
            match1 = new Regex(@"(\[em([\S\t]*?)\])", RegexOptions.IgnoreCase).Match(outPut.ToString());
            while (match1.Success)
            {
                outPut.Replace(match1.Groups[0].Value,
                    "<img src=Images/ubb/face/" + match1.Groups[2].Value + ".gif border=0 align=middle>");
                match1 = match1.NextMatch();
            }
            match1 = new Regex(@"(\[img\])([ \S\t]*?)(\[\/img\])", RegexOptions.IgnoreCase).Match(outPut.ToString());
            while (match1.Success)
            {
                outPut.Replace(match1.Groups[0].Value,
                    "<a target=_blank href=" + match1.Groups[2].Value + "><IMG SRC=" + match1.Groups[2].Value +
                    " border=0 onload='javascript:if(screen.width-333<this.width)this.width=screen.width-333'></a>");
                match1 = match1.NextMatch();
            }

            match1 =
                new Regex(@"(\[flash=)(\d*?),(\d*?)\]([\S\t]*?)(\[\/flash\])", RegexOptions.IgnoreCase).Match(
                    outPut.ToString());
            while (match1.Success)
            {
                outPut.Replace(match1.Groups[0].Value,
                    "<a href=" + match1.Groups[4].ToString() +
                    " TARGET=_blank><IMG SRC=images/swf.gif border=0> [\u5168\u5c4f\u6b23\u8d4f]</a><br><br><OBJECT codeBase=http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,29,0 classid=clsid:D27CDB6E-AE6D-11cf-96B8-444553540000 width=" +
                    match1.Groups[2].Value + " height=" + match1.Groups[3].ToString() + "><PARAM NAME=movie VALUE=" +
                    match1.Groups[4].ToString() +
                    "><PARAM NAME=quality VALUE=high><param name=menu value=false><embed src=" +
                    match1.Groups[4].ToString() +
                    " quality=high menu=false pluginspage=http://www.macromedia.com/go/getflashplayer type=application/x-shockwave-flash width=" +
                    match1.Groups[2].Value + " height=" + match1.Groups[3].ToString() + ">" +
                    match1.Groups[4].ToString() + "</embed></OBJECT>");
                match1 = match1.NextMatch();
            }
            match1 = new Regex(@"(\[dir=)(\d*?),(\d*?)\]([\S\t]*?)(\[\/dir\])", RegexOptions.IgnoreCase).Match(str);
            while (match1.Success)
            {
                outPut.Replace(match1.Groups[0].Value,
                    "<object classid=clsid:166B1BCA-3F9C-11CF-8075-444553540000 codebase=http://download.macromedia.com/pub/shockwave/cabs/director/sw.cab#version=7,0,2,0 width=" +
                    match1.Groups[2].Value + " height=" + match1.Groups[3].ToString() + "><param name=src value=" +
                    match1.Groups[4].ToString() + "><embed src=" + match1.Groups[4].ToString() +
                    " pluginspage=http://www.macromedia.com/shockwave/download/ width=" + match1.Groups[2].Value +
                    " height=" + match1.Groups[3].ToString() + "></embed></object>");
                match1 = match1.NextMatch();
            }
            match1 =
                new Regex(@"(\[rm=)(\d*?),(\d*?),([\S\t]*?)\]([\S\t]*?)(\[\/rm\])", RegexOptions.IgnoreCase).Match(
                    outPut.ToString());
            while (match1.Success)
            {
                outPut.Replace(match1.Groups[0].Value,
                    "<OBJECT classid=clsid:CFCDAA03-8BE4-11cf-B84B-0020AFBBCCFA class=OBJECT id=RAOCX width=" +
                    match1.Groups[2].Value + " height=" + match1.Groups[3].ToString() + "><PARAM NAME=SRC VALUE=" +
                    match1.Groups[5] +
                    "><PARAM NAME=CONSOLE VALUE=Clip1><PARAM NAME=CONTROLS VALUE=imagewindow><PARAM NAME=AUTOSTART VALUE=" +
                    match1.Groups[4].ToString() +
                    "></OBJECT><br><OBJECT classid=CLSID:CFCDAA03-8BE4-11CF-B84B-0020AFBBCCFA height=32 id=video2 width=" +
                    match1.Groups[2].Value + "><PARAM NAME=SRC VALUE=" + match1.Groups[5].ToString() +
                    "><PARAM NAME=AUTOSTART VALUE=" + match1.Groups[4] +
                    "><PARAM NAME=CONTROLS VALUE=controlpanel><PARAM NAME=CONSOLE VALUE=Clip1></OBJECT>");
                match1 = match1.NextMatch();
            }
            match1 =
                new Regex(@"(\[mp=)(\d*?),(\d*?),([\S\t]*?)\]([\S\t]*?)(\[\/mp\])", RegexOptions.IgnoreCase).Match(
                    outPut.ToString());
            while (match1.Success)
            {
                outPut.Replace(match1.Groups[0].Value,
                    "<object align=middle classid=CLSID:22d6f312-b0f6-11d0-94ab-0080c74c7e95 class=OBJECT id=MediaPlayer width=" +
                    match1.Groups[2].Value + " height=" + match1.Groups[3].ToString() + " ><PARAM NAME=AUTOSTART VALUE=" +
                    match1.Groups[4] + "><param name=Filename value=" + match1.Groups[5].ToString() +
                    "><PARAM NAME=showstatusbar VALUE=1><embed type=application/x-oleobject codebase=http://activex.microsoft.com/activex/controls/mplayer/en/nsmp2inf.cab#Version=5,1,52,701 flename=mp src=" +
                    match1.Groups[5].ToString() + "  width=" + match1.Groups[2].Value + " height=" +
                    match1.Groups[3].ToString() + " showstatusbar=1></embed></object>");
                match1 = match1.NextMatch();
            }
            match1 =
                new Regex(@"(\[qt=)(\d*?),(\d*?)\]([\S\t]*?)(\[\/qt\])", RegexOptions.IgnoreCase).Match(
                    outPut.ToString());
            while (match1.Success)
            {
                outPut.Replace(match1.Groups[0].Value,
                    "<embed src=" + match1.Groups[4].ToString() + " width=" + match1.Groups[2].Value + " height=" +
                    match1.Groups[3].ToString() +
                    " autoplay=true loop=false controller=true playeveryframe=false cache=false scale=TOFIT bgcolor=#000000 kioskmode=false targetcache=false pluginspage=http://www.apple.com/quicktime/>");
                match1 = match1.NextMatch();
            }

            match1 = new Regex(@"(\[QUOTE\])([ \S\t]*?)(\[\/QUOTE\])", RegexOptions.IgnoreCase).Match(outPut.ToString());
            while (match1.Success)
            {
                outPut.Replace(match1.Groups[0].Value,
                    "以下内容为引用：<table border=0 width=95% cellpadding=10 cellspacing=1 bgcolor=#000000><tr><td bgcolor=#FFFFFF>" +
                    match1.Groups[2].Value + "</td></tr></table>");
                match1 = match1.NextMatch();
            }
            match1 = new Regex(@"(\[move\])([ \S\t]*?)(\[\/move\])", RegexOptions.IgnoreCase).Match(outPut.ToString());
            while (match1.Success)
            {
                outPut.Replace(match1.Groups[0].Value,
                    "<MARQUEE scrollamount=3>" + match1.Groups[2].Value + "</MARQUEE>");
                match1 = match1.NextMatch();
            }
            match1 = new Regex(@"(\[FLY\])([ \S\t]*?)(\[\/FLY\])", RegexOptions.IgnoreCase).Match(outPut.ToString());
            while (match1.Success)
            {
                outPut.Replace(match1.Groups[0].Value,
                    "<MARQUEE width=80% behavior=alternate scrollamount=3>" + match1.Groups[2].Value + "</MARQUEE>");
                match1 = match1.NextMatch();
            }
            Regex regex1 = new Regex(@"(\[image\])([ \S\t]*?)(\[\/image\])", RegexOptions.IgnoreCase);
            for (match1 = regex1.Match(outPut.ToString()); match1.Success; match1 = match1.NextMatch())
            {
                outPut.Replace(match1.Groups[0].Value,
                    "<img src=\"" + match1.Groups[2].Value + "\" border=0 align=middle><br>");
            }
            return outPut.ToString();
        }

        #endregion

        #region 压缩HTML

        /// <summary>
        ///     压缩HTML
        /// </summary>
        /// <param name="strHtml"></param>
        /// <returns></returns>
        public static string Compress(string strHtml)
        {
            strHtml = Regex.Replace(strHtml, @">\s+\r", ">");
            strHtml = Regex.Replace(strHtml, @">\s+\n", ">");
            strHtml = Regex.Replace(strHtml, @">\s+<", "><");

            return strHtml;
        }

        #endregion

        #region 按字节长度截取字符串(支持截取带HTML代码样式的字符串)

        /// <summary>
        ///     按字节长度截取字符串(支持截取带HTML代码样式的字符串)
        /// </summary>
        /// <param name="param">将要截取的字符串参数</param>
        /// <param name="length">截取的字节长度</param>
        /// <param name="end">字符串末尾补上的字符串</param>
        /// <returns>返回截取后的字符串</returns>
        public static string SubStringHtml(string param, int length, string end)
        {
            string pattern = null;
            MatchCollection m = null;
            StringBuilder result = new StringBuilder();
            int n = 0;
            bool isCode = false; //是不是HTML代码
            bool isHtml = false; //是不是HTML特殊字符,如&nbsp;
            char[] pchar = param.ToCharArray();
            foreach (char t in pchar)
            {
                char temp = t;
                if (temp == '<')
                {
                    isCode = true;
                }
                else if (temp == '&')
                {
                    isHtml = true;
                }
                else if (temp == '>' && isCode)
                {
                    n = n - 1;
                    isCode = false;
                }
                else if (temp == ';' && isHtml)
                {
                    isHtml = false;
                }
                if (!isCode && !isHtml)
                {
                    n = n + 1;
                    //UNICODE码字符占两个字节
                    if (Encoding.Default.GetBytes(temp + "").Length > 1)
                    {
                        n = n + 1;
                    }
                }
                result.Append(temp);
                if (n >= length)
                {
                    break;
                }
            }
            result.Append(end);
            //取出截取字符串中的HTML标记
            string tempResult = result.ToString().Replace("(>)[^<>]*(<?)", "$1$2");
            //去掉不需要结素标记的HTML标记
            tempResult =
                tempResult.Replace(
                    @"</?(AREA|BASE|BASEFONT|BODY|BR|COL|COLGROUP|DD|DT|FRAME|HEAD|HR|HTML|IMG|INPUT|ISINDEX|LI|LINK|META|OPTION|P|PARAM|TBODY|TD|TFOOT|TH|THEAD|TR|area|base|basefont|body|br|col|colgroup|dd|dt|frame|head|hr|html|img|input|isindex|li|link|meta|option|p|param|tbody|td|tfoot|th|thead|tr)[^<>]*/?>",
                    "");
            //去掉成对的HTML标记
            tempResult = tempResult.Replace(@"<([a-zA-Z]+)[^<>]*>(.*?)</\1>", "$2");
            //用正则表达式取出标记
            pattern = ("<([a-zA-Z]+)[^<>]*>");
            m = Regex.Matches(tempResult, pattern);
            List<string> endHtml = (from Match mt in m select mt.Result("$1")).ToList();
            //补全不成对的HTML标记
            for (int i = endHtml.Count - 1; i >= 0; i--)
            {
                result.Append("</");
                result.Append(endHtml[i]);
                result.Append(">");
            }
            return result.ToString();
        }

        #endregion
    }

    /// <summary>
    ///     网页标签
    /// </summary>
    [Flags]
    public enum WebSourceTag : int
    {
        /// <summary>
        ///     无
        /// </summary>
        None = 0,

        /// <summary>
        ///     html
        /// </summary>
        Html = 1,

        /// <summary>
        ///     备注
        /// </summary>
        Note = 2,

        /// <summary>
        ///     脚本
        /// </summary>
        Script = 4,

        /// <summary>
        ///     样式
        /// </summary>
        Style = 8,

        /// <summary>
        ///     标签直接的多余空行
        /// </summary>
        Invisible = 16,

        /// <summary>
        ///     全部
        /// </summary>
        All = Html | Note | Script | Style | Invisible
    }
}